<!--
参数说明：
  width: 代表父元素的宽度
  minHeight 图片最小的高度
  maxHeight 图片的最大高度
  imageInfo 数组用来获取图片信息。
函数说明： imgClick => 返回img点击事情和img锁对应的值
-->
<template>
  <div class="photo-wall" :style="getPhotoWall">
    <div id="photoWall" class="images" @click="clickImg">
      <div v-for="item in imageArr" :key="item.url" :style="getImgStyle(item)" class="img">
        <div :data-info="JSON.stringify(item)" :style="getImgItemStyle(item)">
          <img :data-info="JSON.stringify(item)" :src="item.url" />
        </div>
      </div>
    </div>
  </div>
</template>

<script>

export default {
  name: 'PhotoWall',
  props: {
    width: {
      type: Number,
      default: 300
    },
    mixHeight: {
      type: Number,
      default: 100
    },
    maxHeight: {
      type: Number,
      default: 1000
    },
    xSpacing: {
      type: Number,
      default: 8
    },
    ySpacing: {
      type: Number,
      default: 8
    },
    /**
    * [{url, width, height, info}] info 用于用户需要保持的信息, width/height 代表图片的真实值，不存在则自己计算。
    **/
    imageInfo: {
      type: Array,
      default: () => {
        return []
      }
    }
  },
  data() {
    return {
      imageArr: []
    }
  },
  computed: {
    getPhotoWall() {
      return {
        '--width': this.width + 'px',
        '--maxHeight': this.maxHeight + 'px'
      }
    }
  },
  watch: {
    imageInfo: {
      handler(data) {
        if (data && data.length > 0) {
          if (data[0].width) {
            this.imageArr = data
          } else {
            const promiseArr = data.map(item => {
              return this.getImg(item.url)
            })
            Promise.all(promiseArr).then(result => {
              this.imageArr = result.map((item, index) => {
                return {
                  ...item,
                  info: data[index].info
                }
              })
            })
          }
        }
      },
      deep: true,
      immediate: true
    }
  },
  methods: {
    getImgStyle(item) {
      const scale = item.width / item.height
      return {
        width: this.mixHeight * scale + 'px',
        flexGrow: this.mixHeight * scale,
        marginRight: this.xSpacing + 'px',
        marginBottom: this.ySpacing + 'px'
      }
    },
    getImgItemStyle(item) {
      const paddingBottom = item.height / item.width * 100 + '%'
      return {
        paddingBottom,
        height: 0
      }
    },
    getImg(imageSrc) {
      return new Promise((resolve, reject) => {
        const img = new Image()
        img.src = imageSrc
        img.onload = () => {
          resolve({ width: img.width, height: img.height, url: imageSrc })
        }
        img.onerror = () => {
          reject()
        }
      })
    },
    clickImg(e) {
      e.stopPropagation()
      console.log(e.target.dataset.info, JSON.parse(e.target.dataset.info), 'click')
      this.$emit('imgClick', JSON.parse(e.target.dataset.info))
    }
  }
}
</script>

<style lang="scss" scoped>
.photo-wall {
  width: var(--width) !important;

  .images {
    width: 100%;
    display: flex;
    flex-wrap: wrap;
    &::after {
      content: ' ';
      flex-grow: 999999;
    }
    & > .img {
      position: relative;
      max-height: var(--maxHeight);
      background-color: transparent;

      img { max-width: 100%;
        min-width: 100%;
        max-height: var(--maxHeight);
        object-fit: cover;
        vertical-align: bottom;
      }
    }
  }
}
</style>
